public class Deadlock {
public static void main(String[] args) {
final Object a = new Object();
final Object b = new Object();
new Thread() {
@Override
public void run() {
synchronized (a) {
/* wait for a second to make it likely the other thread can acquire b */
try { Thread.sleep(1000); } catch (Exception e) { }
synchronized (b) {
System.out.println("Acquired a, then b.");
}
}
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (b) {
/* wait for a second to make it likely the other thread can acquire a */
try { Thread.sleep(1000); } catch (Exception e) { }
synchronized (a) {
System.out.println("Acquired b, then a.");
}
}
}
}.start();
}
}
# 1 楼答案
互斥是同步块的关键。不正确使用synchronized block/mutex变量会导致死锁
# 2 楼答案
下面是一个如何在Java中激发deadlock的具体示例。我们产生两个线程。第一个获取
a
上的互斥锁,然后等待第二个,然后尝试获取b
上的锁。第二个获取b
上的锁,然后等待,然后尝试获取a
。结果是程序进入死锁并永远运行注意,这段代码不能保证进入死锁状态。线程调度程序完全有权在启动第二个线程之前运行第一个线程,或者反之亦然。由于本例中的大量等待时间,几乎可以肯定系统将进入死锁状态,但如果不是休眠一秒钟,而是在每次获取锁之前,两个线程都在进行可变时间长度的计算,则以下任何情况都可能随机发生:
"Acquired a, then b."
,然后是"Acquired b, then a."
"Acquired b, then a."
,然后是"Acquired a, then b."
如何防止这种情况发生
看看java.util.concurrent包。里面有很多好吃的东西,可以照顾到很多真正毛茸茸的部分
此外,我不能夸大线程在意外位置切换的程度。一个常见的错误是逐行查看每个线程,想象这些线程可以以不同的方式交错。但这还不够:一个线程可能会在某个库中某个嵌套函数调用的中间被切换出去。p>